package com.example.mybatis_plus_use.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mybatis_plus_use.Exception.CustomException;
import com.example.mybatis_plus_use.Interceptor.JwtUtil;
import com.example.mybatis_plus_use.ValidationGroups.ValidationGroups.LoginGroup;
import com.example.mybatis_plus_use.ValidationGroups.ValidationGroups.RegisterGroup;
import com.example.mybatis_plus_use.dto.UserLogindto;
import com.example.mybatis_plus_use.dto.UserRegisterDto;
import com.example.mybatis_plus_use.entity.User;
import com.example.mybatis_plus_use.enums.Education;
import com.example.mybatis_plus_use.utils.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 用户管理控制器
 * 处理用户相关的所有HTTP请求
 */
@Slf4j
@RequestMapping("/user") // 定义请求的基础路径
@RestController // 声明这是一个 REST 控制器
@Validated  // 开启验证
@Tag(name = "用户管理", description = "用户相关接口") // Swagger 注解，描述接口的功能
public class UserController extends BaseController {

    /**
     * 获取所有用户信息
     *
     * @return 包含所有用户信息的Result对象
     */
    @Operation(summary = "获取所有用户", description = "获取系统中所有用户的列表") // Swagger 注解，描述接口功能
    @ApiResponses(value = { // Swagger 注解，定义接口响应
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @GetMapping("/GetAllUser") // 定义 GET 请求的路径
    public Result<List<User>> GetAllUser() {
        List<User> users = userService.list(); // 获取所有用户
        return Result.success(users); // 返回成功结果
    }

    /**
     * 测试接口
     *
     * @return 包含测试消息的Result对象
     */
    @Operation(summary = "测试接口", description = "返回固定的测试消息") // Swagger 注解
    @ApiResponse(responseCode = "200", description = "调用成功",
            content = @Content(mediaType = "application/json",
                    schema = @Schema(implementation = Result.class))) // 返回结果的类型
    @GetMapping("/mmh") // 定义 GET 请求的路径
    public Result<String> mmh() {
        return Result.success("我米米会来啦hhh"); // 返回测试消息
    }

    /**
     * 分页获取用户信息
     *
     * @param pageNum  当前页码
     * @param pageSize 每页记录数
     * @return 分页用户信息的Result对象
     */
    @Operation(summary = "分页获取用户", description = "根据页码和每页记录数获取用户列表") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @GetMapping("/page") // 定义 GET 请求的路径
    public Result<IPage<User>> page(@RequestParam(defaultValue = "1") Integer pageNum,
                                    @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<User> page = new Page<>(pageNum, pageSize); // 创建分页对象
        IPage<User> userIPage = userService.page(page); // 获取分页用户信息
        return Result.success(userIPage); // 返回成功结果
    }

    /**
     * 根据模糊姓名获取用户信息
     *
     * @param partialName 模糊姓名
     * @return 匹配的用户信息的Result对象
     */
    @Operation(summary = "根据模糊姓名获取用户", description = "根据部分姓名获取用户列表") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @GetMapping("/GetUserByPartialName") // 定义 GET 请求的路径
    public Result<List<User>> GetUserByPartialName(@RequestParam String partialName) {
        List<User> users = userService.GetUserByPartialName(partialName); // 根据模糊姓名获取用户
        return Result.success(users); // 返回成功结果
    }

    /**
     * 根据用户ID获取用户及其订单详情
     *
     * @param id 用户ID
     * @return 用户及其订单详情的Result对象
     */
    @Operation(summary = "获取用户及订单详情", description = "根据用户ID获取用户及其相关订单信息") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @GetMapping("/GetUserAndOrderDetailByid/{id}") // 定义 GET 请求的路径
    public Result<List<User>> GetUserAndOrderDetailByid(@PathVariable Integer id) {
        List<User> users = userService.GetUserAndOrderDetailByid(id); // 根据用户ID获取用户及订单详情
        return Result.success(users); // 返回成功结果
    }

    /**
     * 添加或更新用户信息
     *
     * @param user 用户对象
     * @return 操作结果的Result对象
     */

    /**
     * 更新用户信息
     *
     * @param user 用户对象
     * @return 更新结果的Result对象
     */
    @Operation(summary = "更新用户", description = "根据用户信息更新用户") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "更新成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @PostMapping("/update") // 定义 POST 请求的路径
    public Result<String> update(@RequestBody User user) {
        userService.updateById(user); // 更新用户信息
        return Result.success("更新成功"); // 返回成功结果
    }

    /**
     * 根据用户ID删除用户
     *
     * @param id 用户ID
     * @return 删除结果的Result对象
     */
    @Operation(summary = "删除用户", description = "根据用户ID删除用户") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "删除成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @DeleteMapping("/delete/{id}") // 定义 DELETE 请求的路径
    public Result<String> delete(@PathVariable Integer id) {
        userService.removeById(id); // 根据用户ID删除用户
        return Result.success("删除成功"); // 返回成功结果
    }

    /**
     * 批量删除用户
     *
     * @param ids 用户ID列表
     * @return 批量删除结果的Result对象
     */
    @Operation(summary = "批量删除用户", description = "根据用户ID列表批量删除用户") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "批量删除成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @DeleteMapping("/deleteBatch") // 定义 DELETE 请求的路径
    public Result<String> deleteBatch(@RequestBody List<Integer> ids) {
        userService.removeByIds(ids); // 批量删除用户
        return Result.success("批量删除成功"); // 返回成功结果
    }

    /**
     * 根据用户名删除用户
     *
     * @param name 用户名
     * @return 删除结果的Result对象
     */
    @Operation(summary = "根据用户名删除用户", description = "根据用户名删除用户") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "删除成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @DeleteMapping("/deleteUsersByName") // 定义 DELETE 请求的路径
    public Result<String> deleteUsersByNameLike(@RequestParam String name) {
        userService.removeByMap(Map.of("username", name)); // 根据用户名删除用户
        return Result.success("删除成功"); // 返回成功结果
    }
//// 创建一个只有一个键值对的 Map：
//// key 是 "username"，value 是 name 变量的值
//Map<String, Object> map = Map.of("username", name);

    /**
     * 根据用户名和年龄删除用户
     *
     * @param name 用户名
     * @param age  年龄
     * @return 删除结果的Result对象
     */
    @Operation(summary = "根据用户名和年龄删除用户", description = "根据用户名和年龄删除用户") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "删除成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @DeleteMapping("/deleteUsersByNameAndAge") // 定义 DELETE 请求的路径
    public Result<String> deleteUsersByNameAndAge(@RequestParam String name, @RequestParam Integer age) {
        Map<String, Object> map = new HashMap<>(); // 创建条件Map
        map.put("username", name); // 添加用户名条件
        map.put("age", age); // 添加年龄条件
        userService.removeByMap(map); // 根据条件删除用户
        return Result.success("删除成功"); // 返回成功结果
    }

    /**
     * 根据年龄获取用户信息
     *
     * @param age 年龄
     * @return 匹配的用户信息的Result对象
     */
    @Operation(summary = "根据年龄获取用户", description = "根据年龄获取用户列表") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @GetMapping("/GetUserByAge") // 定义 GET 请求的路径
    public Result<List<User>> GetUserByAge(@RequestParam Integer age) {
        Map<String, Object> map = new HashMap<>(); // 创建条件Map
        map.put("age", age); // 添加年龄条件
        List<User> users = userService.listByMap(map); // 根据条件获取用户
        return Result.success(users); // 返回成功结果
    }

    /**
     * 批量插入用户数据
     *
     * @param users 用户对象列表
     * @return 批量保存结果的Result对象
     */
    @Operation(summary = "批量插入用户", description = "批量插入用户数据") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "批量保存成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @PostMapping("/SaveBatchUser") // 定义 POST 请求的路径
    public Result<String> saveBatchUser(@RequestBody List<User> users) {
        userService.saveBatch(users); // 批量插入用户数据
        return Result.success("批量保存成功"); // 返回成功结果
    }

    @Operation(summary = "根据年龄获取用户", description = "根据年龄获取用户列表") // Swagger 注解
    @ApiResponses(value = { // Swagger 注解
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))), // 返回结果的类型
            @ApiResponse(responseCode = "404", description = "未找到用户"), // 用户未找到响应
            @ApiResponse(responseCode = "500", description = "服务器错误") // 服务器错误响应
    })
    @PostMapping("/SaveUser") // 定义 POST 请求的路径
    public Result<String> saveUser(@RequestBody User user) {
        return userService.SaveUser(user); // 返回成功结果
    }

    /**
     * 获取所有教育程度选项
     */
    @Operation(summary = "获取教育程度列表", description = "获取所有可用的教育程度选项")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(mediaType = "application/json",
                            schema = @Schema(implementation = Result.class))),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/list")
    public Result<List<Map<String, Object>>> getEducationList() {
        List<Map<String, Object>> list = Arrays.stream(Education.values())
                .map(education -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("value", education.getLevel());
                    map.put("desc", education.getDesc());
                    return map;
                }).collect(Collectors.toList());
        return Result.success(list);
    }

    /**
     * 根据等级获取教育程度描述
     */
    @Operation(summary = "获取教育程度描述", description = "根据教育等级获取对应的描述信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "未找到对应等级"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/{level}")
    public Result<?> getEducationDesc(@PathVariable Integer level) {
        return Result.success(userService.getEducationDesc(level));
    }

    /**
     * 获取特定学历及以上的用户
     */
    @Operation(summary = "获取特定学历以上用户", description = "获取大于等于指定学历等级的所有用户")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/getUsersByMinEducation/{minLevel}")
    public Result<?> getUsersByMinEducation(@PathVariable Integer minLevel) {
        return Result.success(userService.getUsersByMinEducation(minLevel));
    }

    /**
     * 更新用户教育程度
     */
    @Operation(summary = "更新用户教育程度", description = "更新指定用户的教育程度")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "更新成功"),
            @ApiResponse(responseCode = "404", description = "用户不存在"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @PutMapping("/user/{userId}")
    public Result<?> updateUserEducation(
            @PathVariable Long userId,
            @RequestParam Integer level) {
        userService.updateUserEducation(userId, level);
        return Result.success();
    }

    /**
     * 根据教育程度获取用户
     */
    @Operation(summary = "根据教育程度获取用户", description = "获取指定教育程度的所有用户")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "无效的教育程度"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/getUsersByEducation/{level}")
    public Result<?> getByEducation(@PathVariable Integer level) {
        List<Education> educationList = Arrays.stream(Education.values())
                .filter(edu -> edu.getLevel() == level)
                .collect(Collectors.toList());  // 收集为列表
//.findFirst() 返回的是 Optional<Education>（单个对象），不能直接调用 .toList()。
        if (educationList.isEmpty()) {
            throw new CustomException("无效的教育程度");
        }
//Education.values()返回的是枚举类中的所有枚举对象的数组，
        return Result.success(educationList);
    }

    /**
     * 获取用户按教育程度分组
     */
    @Operation(summary = "获取用户教育程度分组", description = "获取所有用户按教育程度分组的统计信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/getUsersGroupByEducationLevel")
    public Result<?> getUsersGroupByEducationLevel() {
        return Result.success(userService.getUsersGroupByEducationLevel());// 根据教育程度分组
    }

    /**
     * 获取特定教育程度的用户分组
     */
    @Operation(summary = "获取特定教育程度用户分组", description = "获取指定教育程度的用户分组信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "无效的教育程度"),
            @ApiResponse(responseCode = "500", description = "服务器错误")
    })
    @GetMapping("/getUsersGroupByEducationLevelN/{education}")
    public Result<?> getUsersGroupByEducationLevelN(@PathVariable Integer education) {
        return Result.success(userService.getUsersGroupByEducationLevelN(education));
    }

    //controller层的接口方法的Result返回值，可以返回任意类型，所以可以在<>里写？不要指定类型
    @PostMapping("/login")
    public Result<?> login(@RequestBody @Validated(LoginGroup.class) UserLogindto loginDto) {
        try {
            // 1. 转换DTO到实体 BeanUtil.copyProperties方法会自动过滤双方没有的属性，设置为null
            User userQuery = BeanUtil.copyProperties(loginDto, User.class);

            // 2. 查询用户
            User user = userService.lambdaQuery()
                    .eq(User::getUsername, userQuery.getUsername())
                    .one();//获取用户名为loginDto.getUsername的user的一个对象

            if (user == null) {
                return Result.error("用户不存在");
            }

            // 3. 密码校验
            if (!passwordEncoder.matches(loginDto.getPassword() , user.getPassword())) {
                log.error("登录失败！ 用户名: "+loginDto.getUsername());
                return Result.error("密码错误");
            }

            // 4. 生成token
            String token = JwtUtil.generateToken(user.getUsername());

            return Result.success("token为: " + token);

        } catch (Exception e) {
            log.error("登录失败:", e);
            return Result.error("登录失败: " + e.getMessage());
        }
    }
    @PostMapping("/register")
    public Result<?> register(@RequestBody @Validated(RegisterGroup.class) UserRegisterDto registerDto) {
        try {
            // 1. 检查用户名是否已存在
            User existUser = userService.lambdaQuery()
                    .eq(User::getUsername, registerDto.getUsername())
                    .one();
            //post过来的数据在数据库中没有时会返回null
            if (existUser != null) {
                log.error("用户名已存在!");
                return Result.error("用户名已存在");
            }
            // 2. DTO转换为实体 用hutool的BeanUtil工具类进行转换并加强密码
            User user = BeanUtil.copyProperties(registerDto, User.class);
            String encodedPassword = passwordEncoder.encode(user.getPassword());//加密密码
            user.setPassword(encodedPassword);//加强密码后存入数据库

            // 3. 补充其他字段
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());

            // 4. 保存用户
            userService.save(user);
            log.info("注册成功！ 用户名: " + registerDto.getUsername());
            return Result.success("注册成功");

        } catch (Exception e) {
            log.error("注册失败:", e);
            return Result.error("注册失败: " + e.getMessage());
        }
    }
    @GetMapping("/getUserByid/{id}")
    public Result<?> getUserById(@RequestParam Integer id) {
        User user = userService.getById(id);
        return Result.success(user);
    }

}
